/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package estsapp.controladores.ABMProductoIntermedio;

import autocompletar.logica.ModeloAutoCompletar;
import estsapp.controladores.ABMClasificacionProducto.ControladorABMClasificacionProducto;
import estsapp.controladores.ABMProducto.PantallaABMProducto;
import estsapp.controladores.ABMProducto.PantallaProductoTerminadoJDialog;
import estsapp.controladores.Controlador;
import estsapp.controladores.ControladorPrincipal;
import estsapp.controladores.FabricaControladores;
import estsapp.entidades.ClasificacionProducto;
import estsapp.entidades.DetalleProducto;
import estsapp.entidades.DetalleProductoIntermedio;
import estsapp.entidades.Material;
import estsapp.entidades.Pieza;
import estsapp.entidades.ProductoIntermedio;
import estsapp.entidades.ProductoTerminado;
import estsapp.expertos.ExpertoABMMaterial;
import estsapp.expertos.ExpertoABMProductoIntermedio;
import estsapp.expertos.FabricaExpertos;
import estsapp.expertos.excepciones.ABMProductoIntermedioExeption;
import estsapp.utiles.filtrosTexto.AgregarFiltroTextField;
import estsapp.utiles.modeloComboGenerico.ModeloComboGenerico;
import estsapp.utiles.modeloTabla.ModeloTabla;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import persistencia.exceptions.ExcepcionFachada;

/**
 *
 * @author diego
 */
public class ControladorABMProductoIntermedio implements Controlador {

    private PantallaABMProducto pantalla;
    private ExpertoABMProductoIntermedio experto;
    ExpertoABMMaterial consultarMaterial;
    private ProductoIntermedio productoSeleccionado;
    private ProductoTerminado productoRelacionado; // es el producto terminado relacionado, sirve para comparar cantidades en los materiales ingresados
    private PantallaProductoTerminadoJDialog pantallaProductoIntJDialog;
    private DetalleProductoIntermedio componenteProductoSeleccionado;
    private boolean iniciado = false;

    public ControladorABMProductoIntermedio() {
        pantalla = new PantallaABMProducto();
        pantallaProductoIntJDialog = new PantallaProductoTerminadoJDialog(null, true);
        pantallaProductoIntJDialog.setLocationRelativeTo(null);

        experto = (ExpertoABMProductoIntermedio) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.ABM_PRODUCTO_INTERMEDIO);
        consultarMaterial = (ExpertoABMMaterial) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.ABM_MATERIAL);
        pantalla.getTblProductos().setModel(new ModeloTablaProductoIntermedio());
        pantalla.getTblProductos().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                seleccionarProducto();
            }
        });
        pantalla.getTblProductos().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    seleccionarProducto();
                    modificarProducto();
                }
            }
        });

        /**
         * ###################################################################################
         * ###################################################################################
         * Barra herramientas
         * ###################################################################################
         * ###################################################################################
         */
        pantalla.getBtnRutaFabricacion().setVisible(false);

        pantalla.getBtnNuevo().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                nuevoProducto();
            }
        });
        pantalla.getBtnModificar().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                modificarProducto();
            }
        });
        pantalla.getBtnSalir().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                salir();
            }
        });
        pantalla.getBtnBaja().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                darBaja();
            }
        });
        /**
         * ###################################################################################
         * ###################################################################################
         * JDialog Producto Terminado
         * ###################################################################################
         * ###################################################################################
         */
        pantallaProductoIntJDialog.getTxtPorcentaje().setVisible(false);
        pantallaProductoIntJDialog.getLblPorcentajeG().setVisible(false);
        pantallaProductoIntJDialog.getTblEstructura().setModel(new ModeloTablaEstructuraProductoIntermedio());
        AgregarFiltroTextField.filtroNumeroDecimal(pantallaProductoIntJDialog.getTxtCantidad(),4);

        pantallaProductoIntJDialog.getTblEstructura().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                seleccionarComponenteProducto();
            }
        });

        pantallaProductoIntJDialog.getBtnGuardar().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                guardarProducto();
            }
        });
        pantallaProductoIntJDialog.getBtnNuevaClasificacion().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                nuevaClasificacion();
            }
        });
        pantallaProductoIntJDialog.getBtnAgregarComponente().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                agregarComponenteProducto();
            }
        });
        pantallaProductoIntJDialog.getBtnQuitar().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                quitarComponente();
            }
        });
        pantallaProductoIntJDialog.getTxtCantidad().addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                seleccionarUnidadMedida();
            }
        });
        pantallaProductoIntJDialog.getBtnNuevoDetalle().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                limpiarCamposAgregarProducto();
            }
        });

    }

    public void setProductoRelacionado(ProductoTerminado productoRelacionado) {
        this.productoRelacionado = productoRelacionado;
    }

    @Override
    public JInternalFrame getPantalla() {
        return pantalla;
    }

    @Override
    public void iniciar() {
        if (!iniciado) {
            ((ControladorPrincipal) FabricaControladores.getInstance().getControlador(FabricaControladores.controladoresNombre.PRINCIPAL)).agregarPantallaInterna(pantalla);
            iniciado = true;
        }
        pantalla.setVisible(true);
        ((ModeloTablaProductoIntermedio) pantalla.getTblProductos().getModel()).setListaElementos(experto.buscarProductosIntermedios());
        pantallaProductoIntJDialog.getAutoCompletarComponente().setModelo(new ModeloAutoCompletar(consultarMaterial.buscarPiezasProductoIntermedio()));

        pantallaProductoIntJDialog.getCbxClasificación().setModel(new ModeloComboGenerico(experto.buscarClasificacionesProductos()));

        if (pantallaProductoIntJDialog.getTxtNombre().getText().length() > 0 && iniciado) {//esta iniciado y se estaba ingresando un producto
            pantallaProductoIntJDialog.setVisible(true);
        }

    }

    private void nuevoProducto() {
        limpiarCampos();
        abrirPantallaProductoTerminado();
    }

    public void limpiarCampos() {
        productoSeleccionado = null;
        pantallaProductoIntJDialog.limpiarCampos();
    }

    public void abrirPantallaProductoTerminado() {
        pantallaProductoIntJDialog.setVisible(true);
    }

    public void guardarProducto() {
        if (productoSeleccionado == null) {
            productoSeleccionado = new ProductoIntermedio();
        }

        productoSeleccionado.setNombre(pantallaProductoIntJDialog.getTxtNombre().getText());

        productoSeleccionado.setClasificacion((ClasificacionProducto) ((ModeloComboGenerico) pantallaProductoIntJDialog.getCbxClasificación().getModel()).getItemSeleccionado());
        productoSeleccionado.setDescripcion(pantallaProductoIntJDialog.getTxtDescripcion().getText());
        productoSeleccionado.setDetalles(((ModeloTabla) pantallaProductoIntJDialog.getTblEstructura().getModel()).getListaElementos());

        try {
            experto.guardar(productoSeleccionado);
        } catch (ABMProductoIntermedioExeption ex) {
            JOptionPane.showMessageDialog(pantalla, ex.getMessage(), "INFORMACIÓN", JOptionPane.INFORMATION_MESSAGE);
            return;
        } catch (ExcepcionFachada ex) {
            JOptionPane.showMessageDialog(pantalla, ex.getMessage(), "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }
        agregarProductoTabla(productoSeleccionado);
        JOptionPane.showMessageDialog(pantalla, "Producto Guardado Correctamente", "INFORMACIÓN", JOptionPane.INFORMATION_MESSAGE);
        pantallaProductoIntJDialog.setVisible(false);

        limpiarCampos();

    }

    private void darBaja() {
        if (productoSeleccionado == null) {
            return;
        }
        try {
            experto.darBaja(productoSeleccionado);
        } catch (ABMProductoIntermedioExeption ex) {
            JOptionPane.showMessageDialog(pantalla, ex.getMessage(), "INFORMACIÓN", JOptionPane.INFORMATION_MESSAGE);
            return;
        } catch (ExcepcionFachada ex) {
            JOptionPane.showMessageDialog(pantalla, ex.getMessage(), "INFORMACIÓN", JOptionPane.ERROR);
            return;
        }
        JOptionPane.showMessageDialog(pantalla, "Baja Producto Realizada Correctamente.", "INFORMACIÓN", JOptionPane.INFORMATION_MESSAGE);
        quitarProducto();
    }

    private void agregarProductoTabla(ProductoIntermedio producto) {
        List productos = ((ModeloTablaProductoIntermedio) pantalla.getTblProductos().getModel()).getListaElementos();
        for (Object object : productos) {
            if (producto.equals(object)) {
                return;
            }
        }
        ((ModeloTablaProductoIntermedio) pantalla.getTblProductos().getModel()).addRow(producto);
    }

    private void seleccionarProducto() {
        limpiarCampos();
        int fila = pantalla.getTblProductos().getSelectedRow();
        if (fila == -1) {
            return;
        }
        int filaModelo = pantalla.getTblProductos().convertRowIndexToModel(fila);
        productoSeleccionado = (ProductoIntermedio) ((ModeloTabla) pantalla.getTblProductos().getModel()).getRow(filaModelo);
        mostrarProducto(productoSeleccionado);
    }

    private void mostrarProducto(ProductoIntermedio producto) {
        pantallaProductoIntJDialog.getTxtNombre().setText(producto.getNombre());
        ((ModeloComboGenerico) pantallaProductoIntJDialog.getCbxClasificación().getModel()).setItemSeleccionado(producto.getClasificacion());
        pantallaProductoIntJDialog.getTxtDescripcion().setText(producto.getDescripcion());

        ((ModeloTabla) pantallaProductoIntJDialog.getTblEstructura().getModel()).setListaElementos(producto.getDetalles());
    }

    private void modificarProducto() {
        if (productoSeleccionado != null) {
            pantallaProductoIntJDialog.setVisible(true);
        }
    }

    private void nuevaClasificacion() {
        pantallaProductoIntJDialog.setVisible(false);
        ControladorABMClasificacionProducto controladorClasificacion = (ControladorABMClasificacionProducto) FabricaControladores.getInstance().getControlador(FabricaControladores.controladoresNombre.ABM_CLASIFICACION_PRODUCTO);
        controladorClasificacion.setIngresandoProductoTerminado(false);
        controladorClasificacion.iniciar();
    }

    private void salir() {
        pantalla.setVisible(false);
        FabricaControladores.getInstance().getControlador(FabricaControladores.controladoresNombre.ABM_RUTA_DE_FABRICACION).iniciar();
    }

    private void quitarProducto() {
        if (productoSeleccionado == null) {
            return;
        }
        List productos = ((ModeloTablaProductoIntermedio) pantalla.getTblProductos().getModel()).getListaElementos();
        for (int i = 0; i < productos.size(); i++) {
            if (productos.get(i).equals(productoSeleccionado)) {
                ((ModeloTabla) pantalla.getTblProductos().getModel()).removeRow(i);
            }
        }
    }

    private void seleccionarComponenteProducto() {
        int fila = pantallaProductoIntJDialog.getTblEstructura().getSelectedRow();
        if (fila == -1) {
            return;
        }
        int filaModelo = pantallaProductoIntJDialog.getTblEstructura().convertRowIndexToModel(fila);
        componenteProductoSeleccionado = (DetalleProductoIntermedio) ((ModeloTabla) pantallaProductoIntJDialog.getTblEstructura().getModel()).getRow(filaModelo);

        pantallaProductoIntJDialog.getAutoCompletarComponente().setItemSeleccionado(componenteProductoSeleccionado.getPieza().getNombreElemento());
        pantallaProductoIntJDialog.getTxtCantidad().setText(componenteProductoSeleccionado.getCantidad().toString());
        pantallaProductoIntJDialog.getCbxUnidadMedida().setSelectedItem(componenteProductoSeleccionado.getUnidadMedida());

    }

    private void agregarComponenteProducto() {
        if (pantallaProductoIntJDialog.getAutoCompletarComponente().getTexto().length() == 0) {
            return;
        }

        if (componenteProductoSeleccionado == null) {
            componenteProductoSeleccionado = new DetalleProductoIntermedio();
        }
        Pieza pieza = (Pieza) pantallaProductoIntJDialog.getAutoCompletarComponente().getItemSeleccionado();
        componenteProductoSeleccionado.setCantidad(Float.valueOf(pantallaProductoIntJDialog.getTxtCantidad().getText()));
        componenteProductoSeleccionado.setPieza(pieza);
        componenteProductoSeleccionado.setUnidadMedida(pantallaProductoIntJDialog.getCbxUnidadMedida().getSelectedItem().toString());
        
        if(piezaInvalida(pieza)){
            JOptionPane.showMessageDialog(pantalla, "La pieza ingresada no forma parte de la estructura de Producto: "+productoRelacionado.getNombre());
            return;
        }

        if (!cantidadValida(componenteProductoSeleccionado)) {
            JOptionPane.showMessageDialog(pantalla, "Producto relacionado: "+productoRelacionado.getNombre()+"\n"
                    + "La cantidad Ingresada de "+pieza.getNombre()+", supera a la cantidad definida en la estructura del producto:\n"
                    + getCantidadDefinida(pieza));
            return;
        }

        for (Object object : ((ModeloTabla) pantallaProductoIntJDialog.getTblEstructura().getModel()).getListaElementos()) {
            if (((DetalleProductoIntermedio) object).getPieza().equals(pieza)) {
                ((ModeloTabla) pantallaProductoIntJDialog.getTblEstructura().getModel()).fireTableDataChanged();
                limpiarCamposAgregarProducto();
                return;
            }
        }
        ((ModeloTablaEstructuraProductoIntermedio) pantallaProductoIntJDialog.getTblEstructura().getModel()).addRow(componenteProductoSeleccionado);
        limpiarCamposAgregarProducto();


    }

    private void limpiarCamposAgregarProducto() {
        pantallaProductoIntJDialog.getAutoCompletarComponente().setTexto("");
        pantallaProductoIntJDialog.getTxtCantidad().setText("");
        pantallaProductoIntJDialog.getCbxUnidadMedida().setSelectedIndex(0);
        componenteProductoSeleccionado = null;
    }

    private void quitarComponente() {
        if (componenteProductoSeleccionado == null) {
            return;
        }
        ((ModeloTabla) pantallaProductoIntJDialog.getTblEstructura().getModel()).removeElement(componenteProductoSeleccionado);
    }

    private void seleccionarUnidadMedida() {
        if (pantallaProductoIntJDialog.getAutoCompletarComponente().getItemSeleccionado() != null) {
            Pieza pieza = (Pieza) pantallaProductoIntJDialog.getAutoCompletarComponente().getItemSeleccionado();
            if (pieza instanceof Material) {
                pantallaProductoIntJDialog.getCbxUnidadMedida().setSelectedItem(((Material) pieza).getUnidadMedida());
            } else {
                pantallaProductoIntJDialog.getCbxUnidadMedida().setSelectedItem("unidad");
            }
        }
    }

    private boolean cantidadValida(DetalleProductoIntermedio detalleProd) {
        if (detalleProd.getPieza() instanceof Material || detalleProd.getPieza() instanceof ProductoTerminado) {
            for (DetalleProducto detalleProducto : productoRelacionado.getDetalles()) {
                if (detalleProducto.getPieza().equals(detalleProd.getPieza())) {
                    if (detalleProducto.getCantidad() < detalleProd.getCantidad()) {
                        return false;
                    } else {
                        return true;
                    }
                }
            }
        }
        return true;
    }
/**
 * Busca la cantidad definida del material o pieza, en la estructura del producto relacionado
 * @param pieza
 * @return 
 */
    private String getCantidadDefinida(Pieza pieza) {
        for (DetalleProducto detalleProducto : productoRelacionado.getDetalles()) {
            if(detalleProducto.getPieza().equals(pieza)){
                return pieza.getNombre()+" cantidad definida = "+detalleProducto.getCantidad();
            }
        }
        return "";
    }

    private boolean piezaInvalida(Pieza pieza) {
        for (DetalleProducto detalleProducto : productoRelacionado.getDetalles()) {
            if(detalleProducto.getPieza().equals(pieza)){
                return false;
            }
        }
        return true;
    }
}
